var express = require("express");
var router = express.Router();

const { Article } = require("../../models");
// 复杂查询
const { Op } = require("sequelize");
// 自定义异常
const { NotFound } = require("http-errors");
// 自定义响应
const { success, failure } = require("../../utils/responses");

/**
 * 获取文章列表
 * GET /admin/articles
 * @query { limit, offset }
 * @return 文章列表
 */
router.get("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    // return res.json({
    //   currentUser: req.user,
    // })
    // 文章的分页查询
    const query = req.query;
    // 当前页码 默认 1
    const currentPage = Math.abs(+query.currentPage) || 1;
    // 每页多少条数据 默认 10
    const pageSize = Math.abs(+query.pageSize) || 10;
    // 偏移量
    const offset = (currentPage - 1) * pageSize;

    const condition = {
      where: {},
      order: [
        ["id", "DESC"],
        // ['createdAt', 'DESC']
      ],
      limit: pageSize,
      offset,
    };

    // 查询被软删除的数据
    if (query.deleted === "true") {
      condition.paranoid = false; // 关闭软删除
      condition.where.deletedAt = { [Op.not]: null }; // 只需要查询被软删除的数据
    }

    // 标题的模糊查询
    if (query.title) {
      condition.where.title = {
        [Op.like]: `%${query.title}%`,
      };
    }
    // 查询所有文章
    const { rows, count } = await Article.findAndCountAll(condition);
    // 成功状态码 默认200 正确响应了
    success(res, "查询文章列表成功", {
      articles: rows,
      pagination: {
        currentPage,
        pageSize,
        total: count,
      },
    });
  } catch (error) {
    failure(res, error);
  }
});
/**
 * 获取文章详情
 * GET /admin/articles/:id
 * @params id 文章id
 * @return 文章详情
 */
router.get("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const article = await getArticle(req);
    // 成功状态码 默认200
    success(res, "查询文章详情成功", { article });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 新增文章
 * POST /admin/articles
 * @body title 标题
 * @body content 内容
 * @return
 */
router.post("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const body = filterBody(req);

    const article = await Article.create(body);
    await clearCache();

    // 成功状态码 201 正确响应了，并创建了新的资源
    success(res, "新增文章成功", article, 201);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 删除文章(单条记录软删除)
 * DELETE /admin/articles/:id
 * @params id 文章id
 * @return
 */
// router.delete("/:id", async function (req, res, next) {
//   // 处理异常 try catch
//   try {
//     const article = await getArticle(req);

//     await article.destroy();

//     success(res, "删除文章成功");
//   } catch (error) {
//     failure(res, error);
//   }
// });

/**
 * 删除到回收站(合并单条软删除和批量软删除), 这里不适合用DELETE请求, Express 默认不会解析 DELETE 请求中的body, 所以需要用POST请求来处理。
 * POST /admin/articles/delete
 */
router.post("/delete", async function (req, res) {
  try {
    const { id } = req.body;

    await Article.destroy({ where: { id: id } });
    await clearCache(id);

    success(res, "已删除到回收站。");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 从回收站恢复
 * POST /admin/articles/restore
 */
router.post("/restore", async function (req, res) {
  try {
    const { id } = req.body;

    await Article.restore({ where: { id: id } });
    await clearCache(id);

    success(res, "已恢复成功。");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 彻底删除
 * POST /admin/articles/force_delete
 */
router.post("/force_delete", async function (req, res) {
  try {
    const { id } = req.body;

    await Article.destroy({
      where: { id: id },
      force: true, // 强制删除
    });
    await clearCache(id);

    success(res, "已彻底删除。");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新文章
 * PUT /admin/articles/:id
 * @params id 文章id
 * @body title 标题
 * @body content 内容
 * @return 文章详情
 */
router.put("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const article = await getArticle(req);
    // 白名单过滤
    const body = filterBody(req);

    await article.update(body);
    await clearCache(article.id);

    success(res, "更新文章成功", { article });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 公共方法: 查询当前文章
 */
async function getArticle(req) {
  // 获取文章ID
  const { id } = req.params;
  // 查询文章
  const article = await Article.findByPk(id);
  // 文章不存在 抛出异常
  if (!article) {
    throw new NotFound(`ID: ${id}的文章不存在`);
  }
  // 文章存在
  return article;
}

/**
 * 白名单过滤
 * @param req
 * @returns {{title, content: (string|*)}}
 */
function filterBody(req) {
  // 只保留白名单字段
  return {
    title: req.body.title,
    content: req.body.content,
  };
}

const { getKeysByPattern, delKey } = require("../../utils/redis");

/**
 * 清除缓存
 * @returns {Promise<void>}
 */
async function clearCache(id = null) {
  // 清除所有文章列表缓存
  const keys = await getKeysByPattern("articles:*");

  if (keys.length !== 0) {
    await delKey(keys);
  }
  // 如果传递了id, 则通过id清除文章详情缓存
  if (id) {
    // id 如果是数组, 则遍历删除
    const keys = Array.isArray(id)
      ? id.map((item) => `article:${item}`)
      : `article:${id}`;

    await delKey(keys);
  }
}

module.exports = router;
